home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1996 May: Tool Chest / Developer CD Series May 1996 (Tool Chest) (Apple Computer) (1996).iso / Tool Chest / Development Tools & Languages / Dylan Related / Mindy / Mindy 1.2 - portable sources / interp / extern.c < prev    next >
Encoding:
C/C++ Source or Header  |  1995-03-15  |  26.2 KB  |  818 lines  |  [TEXT/ttxt]

  1. /**********************************************************************\
  2. *
  3. *  Copyright (C) 1994, Carnegie Mellon University
  4. *  All rights reserved.
  5. *
  6. *  This code was produced by the Gwydion Project at Carnegie Mellon
  7. *  University.  If you are interested in using this code, contact
  8. *  "Scott.Fahlman@cs.cmu.edu" (Internet).
  9. *
  10. ***********************************************************************
  11. *
  12. * $Header: extern.c,v 1.2 94/11/30 16:17:18 rgs Exp $
  13. *
  14. * This file provides support for manipulating native C pointers.
  15. *
  16. \**********************************************************************/
  17.  
  18. #include "../compat/std-c.h"
  19.  
  20. #include "mindy.h"
  21. #include "gc.h"
  22. #include "obj.h"
  23. #include "bool.h"
  24. #include "char.h"
  25. #include "list.h"
  26. #include "type.h"
  27. #include "class.h"
  28. #include "def.h"
  29. #include "sym.h"
  30. #include "module.h"
  31. #include "error.h"
  32. #include "thread.h"
  33. #include "func.h"
  34. #include "extern.h"
  35. #include "num.h"
  36. #include "str.h"
  37. #include "print.h"
  38. #include "coll.h"
  39. #ifdef hp9000s800
  40. #include <sys/file.h>
  41. /*
  42. #include <stdio.h>
  43. #include <stdlib.h>
  44. */
  45. #include <a.out.h>
  46. #include <aouthdr.h>
  47. #include <filehdr.h>
  48. #include <syms.h>
  49. #include <sys/mman.h>
  50. #include <unistd.h>
  51. #endif
  52.  
  53. obj_t obj_CPointerClass = NULL;      /* all instances of StaticTypeClass are
  54.                      subclasses of this one */
  55. obj_t obj_ForeignFileClass = NULL;
  56. obj_t obj_NullPointer = NULL;
  57. obj_t /* <foreign-file> */ mindy_explicit_syms = NULL;
  58.  
  59. static obj_t /* <foreign-file> */ mindy_dynamic_syms = NULL;
  60.  
  61. obj_t make_c_pointer(obj_t /* <static-pointer-class> */ cls, void *ptr)
  62. {
  63.     obj_t res = alloc(cls, sizeof(struct c_pointer));
  64.  
  65.     C_PTR(res)->pointer = ptr;
  66.  
  67.     return res;
  68. }
  69.  
  70. /* Dylan routines. */
  71.  
  72. /* Reads the symtab (in some machine specific format) from the named file 
  73.    and returns a "foreign_file" object which allows access to those symbols */
  74. obj_t  load_c_symtab(obj_t /* <string> */ abs_file)
  75.     int fd, count, total = 0;
  76.     char *file = string_chars(abs_file);
  77.     obj_t res;
  78.     
  79. #if defined(hp9000s800)
  80.     struct header hdr;
  81.     struct symtab *retval;
  82.     int sym_count, sym_size, sym_loc, string_size, string_loc, table_size;
  83.     struct symbol_dictionary_record *syms;
  84.     char *strings;
  85.     int i, j;
  86.  
  87.     /* Read beginning of "file" into "hdr" */
  88.     fd = open(file, O_RDONLY, 0);
  89.     if (fd < 0) return 0;
  90.     for (count = read(fd, ((char *)&hdr), sizeof(hdr)), total = count;
  91.      count > 0 && total < sizeof(hdr);
  92.      count = read(fd, ((char *)&hdr + total), sizeof(hdr) - total),
  93.      total += count) ;
  94.     if (total < sizeof(hdr)) return 0;
  95.  
  96.     /* Read in symbol table */
  97.     sym_count = hdr.symbol_total;
  98.     sym_loc = hdr.symbol_location;
  99.     sym_size = sizeof(struct symbol_dictionary_record) * sym_count;
  100.     if ((syms = (struct symbol_dictionary_record *) malloc(sym_size)) == NULL)
  101.     return 0;
  102.     if (lseek(fd, sym_loc, 0) < 0) return 0;
  103.     for (count = read(fd, (char *) syms, sym_size), total = count;
  104.      count > 0 && total < sym_size;
  105.      count = read(fd, ((char *) syms) + total, sym_size - total),
  106.      total += count) ;
  107.     if (total < sym_size) return 0;
  108.  
  109.     string_size = hdr.symbol_strings_size;
  110.     table_size = (sym_count - 1) * sizeof(struct symtab);
  111.     res = alloc(obj_ForeignFileClass,
  112.         sizeof(struct foreign_file) + table_size + string_size);
  113.     FOREIGN_FILE(res)->extra_size = string_size + table_size;
  114.  
  115.     retval = FOREIGN_FILE(res)->syms;
  116.     strings = (char *)retval + table_size;
  117.  
  118.     /* Read in symbol table strings */
  119.     string_loc = hdr.symbol_strings_location;
  120.     if (lseek(fd, string_loc, 0) < 0) return 0;
  121.     for (count = read(fd, strings, string_size), total = count;
  122.      count > 0 && total < string_size;
  123.      count = read(fd, strings + total, string_size - total),
  124.      total += count) ;
  125.     if (total < string_size) return 0;
  126.  
  127.     close(fd);
  128.  
  129.     if (retval == NULL) return 0;
  130.     for (i = 0, j = 0; i < sym_count; i++)
  131.     if (syms[i].symbol_scope == SS_UNIVERSAL) {
  132.         retval[j].name = strings + syms[i].name.n_strx;
  133.         switch (syms[i].symbol_type) {
  134.         case ST_DATA:
  135.         retval[j++].ptr = (void *) syms[i].symbol_value;
  136.         break;
  137.         case ST_CODE:
  138.         case ST_PRI_PROG:
  139.         case ST_SEC_PROG:
  140.         case ST_ENTRY:
  141.         case ST_MILLICODE:
  142.         retval[j++].ptr = (void *) (syms[i].symbol_value & 0xfffffffc);
  143.         break;
  144.         default:
  145.         retval[j++].ptr = 0;
  146.         }
  147.     }
  148.  
  149.     FOREIGN_FILE(res)->file_name = abs_file;
  150.     FOREIGN_FILE(res)->sym_count = j;
  151.  
  152.     return res;
  153. #else
  154.     return obj_False;
  155. #endif
  156. }
  157.  
  158. /* Links the named object files for dynamic loading, reads it in, and returns
  159.    a "foreign_file" object which allows access to its symbols.  If
  160.    names is a non-empty list (of byte-strings), then make ld "undefine"
  161.    these names so that they will show up in the linked version. */
  162. obj_t load_c_file(obj_t /* list */ c_files, obj_t /* list */ names)
  163. /* c_file is a <string> */
  164. {
  165. #ifdef hp9000s800
  166.     char *execstr;
  167.     int execlimit = 1024, execsize;
  168.     char *absfile;
  169.     obj_t res, file_name = obj_False;
  170.     static int pagesize = 0;
  171.     int fd, count, total, codesize, bss_size, mapresult;
  172.     struct header hdr;
  173.     struct som_exec_auxhdr aux;
  174.     static void *addr = (void *)0x20000000;
  175.  
  176.     if (pagesize == 0) pagesize = sysconf(_SC_PAGE_SIZE);
  177.  
  178.     execstr = malloc(execlimit);
  179.     absfile = tmpnam(NULL);
  180.     sprintf(execstr, "/bin/ld -N -o %s -E -A %s -R %x",
  181.         absfile, exec_file_name, (int) addr);
  182.     execsize = strlen(execstr);
  183.     /* append each object file */
  184.     for ( ; c_files != obj_Nil; c_files = TAIL(c_files)) {
  185.     int flaglen = obj_ptr(struct string *, HEAD(c_files))->len + 1;
  186.     if ((execsize + flaglen + 1) > execlimit) {
  187.         execlimit += 1024;
  188.         execstr = realloc(execstr, execlimit);
  189.     }
  190.     if (file_name == obj_False) file_name = HEAD(c_files);
  191.     sprintf(execstr+execsize, " %s", string_chars(HEAD(c_files)));
  192.     execsize += flaglen;
  193.     }
  194.     /* undefine each of the names we were given */
  195.     for ( ; names != obj_Nil; names = TAIL(names)) {
  196.     int flaglen = obj_ptr(struct string *, HEAD(names))->len + 4;
  197.     if ((execsize + flaglen + 1) > execlimit) {
  198.         execlimit += 1024;
  199.         execstr = realloc(execstr, execlimit);
  200.     }
  201.     sprintf(execstr+execsize, " -u %s", string_chars(HEAD(names)));
  202.     execsize += flaglen;
  203.     }
  204.     if (system(execstr) != 0)
  205.     return NULL;        /* unknown failure */
  206.     
  207.     /* Read beginning of "file" into "hdr" */
  208.     fd = open(absfile, O_RDONLY, 0);
  209.     if (fd < 0) return 0;
  210.     for (count = read(fd, ((char *)&hdr), sizeof(hdr)), total = count;
  211.      count > 0 && total < sizeof(hdr);
  212.      count = read(fd, ((char *)&hdr + total), sizeof(hdr) - total),
  213.      total += count) ;
  214.     if (total < sizeof(hdr)) return NULL;
  215.  
  216.     if (lseek(fd, hdr.aux_header_location, 0) < 0) return NULL;
  217.     for (count = read(fd, ((char *)&aux), sizeof(aux)), total = count;
  218.      count > 0 && total < sizeof(aux);
  219.      count = read(fd, ((char *)&aux + total), sizeof(aux) - total),
  220.      total += count) ;
  221.     if (total < sizeof(aux)) return NULL;
  222.  
  223.     codesize = ((aux.exec_tsize + pagesize - 1) / pagesize) * pagesize;
  224.     mapresult =
  225.     (int) mmap((void *) aux.exec_tmem, codesize,
  226.            PROT_READ | PROT_WRITE | PROT_EXEC,
  227.            MAP_FIXED | MAP_PRIVATE | MAP_FILE, fd, aux.exec_tfile);
  228.     if (mapresult < 0)
  229.     return NULL;
  230.     if (aux.exec_tmem + codesize > (int)addr)
  231.     addr = (void *)(aux.exec_tmem + codesize);
  232.     
  233.     codesize = ((aux.exec_dsize + pagesize - 1) / pagesize) * pagesize;
  234.     if (mmap((void *)aux.exec_dmem, codesize,
  235.          PROT_READ | PROT_WRITE | PROT_EXEC,
  236.          MAP_FIXED | MAP_PRIVATE | MAP_FILE, fd, aux.exec_dfile) < 0)
  237.     return NULL;
  238.  
  239.     bss_size = ((aux.exec_bsize + pagesize - 1) / pagesize) * pagesize;
  240.     if (mmap((void *)(aux.exec_dmem + codesize), bss_size,
  241.          PROT_READ | PROT_WRITE | PROT_EXEC,
  242.          MAP_FIXED | MAP_PRIVATE | MAP_ANONYMOUS, -1, 0) < 0)
  243.     return NULL;
  244.     if (aux.exec_bfill != 0)
  245.     error("Non-zero BSS fill value -- must fix extern.c");
  246.     if (aux.exec_dmem + codesize + bss_size > (int)addr)
  247.     addr = (void *)(aux.exec_dmem + codesize + bss_size);
  248.  
  249.     close(fd);
  250.     
  251.     res = load_c_symtab(make_byte_string(absfile));
  252.     FOREIGN_FILE(res)->file_name = file_name;
  253.     unlink(absfile);
  254.     
  255.     return res;
  256. #else
  257.     error("Dynamic loading is not supported for this architecture.");
  258.     return obj_False;
  259. #endif
  260. }
  261.  
  262. static void print_foreign_file(obj_t file)
  263. {
  264.     printf("{<foreign-file> %s}", string_chars(FOREIGN_FILE(file)->file_name));
  265. }
  266.  
  267. static void print_c_pointer(obj_t ptr)
  268. {
  269.     obj_t class = C_PTR(ptr)->class;
  270.     obj_t class_name = obj_ptr(struct class *, class)->debug_name;
  271.     char *class_str;
  272.  
  273.     if (class_name != NULL && class_name != obj_False)
  274.     class_str = sym_name(class_name);
  275.     else
  276.     class_str = "<c-pointer>";
  277.  
  278.     printf("{%s 0x%08lx}", class_str, (unsigned long)(C_PTR(ptr)->pointer));
  279. }
  280.  
  281. /* Look for an object with the given name in the named file and return a
  282.    callable "<c-function>" object for it. */
  283. obj_t find_c_function(obj_t /* <string> */ symbol, obj_t lookup)
  284. {
  285.     char *string = string_chars(symbol);
  286.     struct symtab *syms;
  287.     int sym_count, i;
  288.     obj_t retval = obj_False;
  289.  
  290.     if (lookup == obj_Unbound) {
  291.     retval = find_c_function(symbol, mindy_explicit_syms);
  292.     if (retval != obj_False) return retval;
  293.  
  294.     if (mindy_dynamic_syms == NULL)
  295.         mindy_dynamic_syms = load_c_symtab(make_byte_string(exec_file_name));
  296.     return find_c_function(symbol, mindy_dynamic_syms);
  297.     } else if (lookup == obj_False)
  298.     return obj_False;
  299.     else if (object_class(lookup) != obj_ForeignFileClass) {
  300.     error("Keyword file: is not a <foreign-file>: %=", lookup);
  301.     return retval;        /* make lint happy */
  302.     } else {
  303.     syms = FOREIGN_FILE(lookup)->syms;
  304.     sym_count = FOREIGN_FILE(lookup)->sym_count;
  305.     for (i = 0; i < sym_count; i++)
  306.         if (strcmp(syms[i].name, string) == 0) {
  307.         retval = make_c_function(make_byte_string(string),
  308.                      syms[i].ptr);
  309.         break;
  310.         }
  311.     return retval;
  312.     }
  313. }
  314.  
  315. /* Look for an object with the given name in the named file and return a
  316.    "<c-pointer>" object for it. */
  317. obj_t find_c_ptr(obj_t /* <string> */ symbol, obj_t lookup)
  318. {
  319.     char *string = string_chars(symbol);
  320.     struct symtab *syms;
  321.     int sym_count, i;
  322.     obj_t retval = obj_False;
  323.  
  324.     if (lookup == obj_Unbound) {
  325.     retval = find_c_ptr(symbol, mindy_explicit_syms);
  326.     if (retval != obj_False) return retval;
  327.  
  328.     if (mindy_dynamic_syms == NULL)
  329.         mindy_dynamic_syms = load_c_symtab(make_byte_string(exec_file_name));
  330.     return find_c_ptr(symbol, mindy_dynamic_syms);
  331.     } else if (lookup == obj_False)
  332.     return obj_False;
  333.     else if (object_class(lookup) != obj_ForeignFileClass) {
  334.     error("Keyword file: is not a <foreign-file>: %=", lookup);
  335.     return retval;        /* make lint happy */
  336.     } else {
  337.     syms = FOREIGN_FILE(lookup)->syms;
  338.     sym_count = FOREIGN_FILE(lookup)->sym_count;
  339.     for (i = 0; i < sym_count; i++)
  340.         if (strcmp(syms[i].name, string) == 0) {
  341.         retval = make_c_pointer(obj_CPointerClass, syms[i].ptr);
  342.         break;
  343.         }
  344.     return retval;
  345.     }
  346. }
  347.  
  348. /* Tries to return a version of some Dylan object which will be
  349.    meaningful to C.  This may include a pointer, an integer, or
  350.    something else.  We assume that it can be freely cast to and from a
  351.    pointer. */
  352. void *get_c_object(obj_t obj)
  353. {
  354.     obj_t cls = object_class(obj);
  355.  
  356.     if (object_class(cls) == obj_StaticTypeClass)
  357.     return C_PTR(obj)->pointer;
  358.     else if (cls == obj_IntegerClass || cls == obj_FixnumClass)
  359.     return (void *)fixnum_value(obj);
  360.     else if (cls == obj_ByteStringClass)
  361.     return (void *)string_chars(obj);
  362.     else if (cls == obj_CharacterClass)
  363.     return (void *)(int)char_int(obj);
  364.     else if (cls == obj_BooleanClass)
  365.     return (void *)(obj != obj_False);
  366.     else
  367.     return NULL;
  368. }
  369.  
  370. /* Tries to convert a C return value back into a dylan object. */
  371. obj_t convert_c_object(obj_t cls, void *obj, boolean miss_ok)
  372. {
  373.     if (cls == obj_ObjectClass)
  374.     return make_c_pointer(obj_CPointerClass, obj);
  375.     else if (object_class(cls) == obj_StaticTypeClass)
  376.     return make_c_pointer(cls, obj);
  377.     else if (cls == obj_CFunctionClass)
  378.     return make_c_function(make_byte_string("(unknown)"), obj);
  379.     else if (cls == obj_IntegerClass || cls == obj_FixnumClass)
  380.     return make_fixnum((int) obj);
  381.     else if (cls == obj_ByteStringClass || cls == obj_StringClass)
  382.     return make_byte_string((char *)obj);
  383.     else if (cls == obj_CharacterClass)
  384.     return int_char((int)obj);
  385.     else if (cls == obj_BooleanClass)
  386.     return obj == NULL ? obj_False : obj_True;
  387.     else if (miss_ok)
  388.     return make_c_pointer(obj_CPointerClass, obj);
  389.     else {
  390.     error("Could not coerce c_pointer to class %=", cls);
  391.     return obj_NullPointer;
  392.     }
  393. }
  394.  
  395. obj_t signed_byte_at(obj_t /* <statically-typed-pointer> */ pointer,
  396.              obj_t /* <integer> */ offset)
  397. {
  398.     void *ptr = C_PTR(pointer)->pointer;
  399.     int true_offset = fixnum_value(offset);
  400.     
  401.     if (!obj_is_fixnum(offset))
  402.     error("Offset is not fixnum: %=", offset);
  403.     return make_fixnum(*((char *)((int)ptr + true_offset)));
  404. }
  405.  
  406. obj_t signed_byte_at_setter(obj_t /* <integer> */ value,
  407.                 obj_t /* <statically-typed-pointer> */ pointer,
  408.                 obj_t /* <integer> */ offset)
  409. {
  410.     void *ptr = C_PTR(pointer)->pointer;
  411.     int true_offset = fixnum_value(offset);
  412.     
  413.     if (!obj_is_fixnum(offset))
  414.     error("Offset is not fixnum: %=", offset);
  415.     *((char *)((int)ptr + true_offset)) = fixnum_value(value);
  416.     return value;
  417. }
  418.  
  419. obj_t unsigned_byte_at(obj_t /* <statically-typed-pointer> */ pointer,
  420.                obj_t /* <integer> */ offset)
  421. {
  422.     void *ptr = C_PTR(pointer)->pointer;
  423.     int true_offset = fixnum_value(offset);
  424.     
  425.     if (!obj_is_fixnum(offset))
  426.     error("Offset is not fixnum: %=", offset);
  427.     return make_fixnum(*((unsigned char *)((int)ptr + true_offset)));
  428. }
  429.  
  430. obj_t unsigned_byte_at_setter(obj_t /* <integer> */ value,
  431.                   obj_t /* <statically-typed-pointer> */ pointer,
  432.                   obj_t /* <integer> */ offset)
  433. {
  434.     void *ptr = C_PTR(pointer)->pointer;
  435.     int true_offset = fixnum_value(offset);
  436.     
  437.     if (!obj_is_fixnum(offset))
  438.     error("Offset is not fixnum: %=", offset);
  439.     *((unsigned char *)((int)ptr + true_offset)) = fixnum_value(value);
  440.     return value;
  441. }
  442.  
  443. obj_t signed_short_at(obj_t /* <statically-typed-pointer> */ pointer,
  444.               obj_t /* <integer> */ offset)
  445. {
  446.     void *ptr = C_PTR(pointer)->pointer;
  447.     int true_offset = fixnum_value(offset);
  448.     
  449.     if (!obj_is_fixnum(offset))
  450.     error("Offset is not fixnum: %=", offset);
  451.     return make_fixnum(*((short *)((int)ptr + true_offset)));
  452. }
  453.  
  454. obj_t signed_short_at_setter(obj_t /* <integer> */ value,
  455.                  obj_t /* <statically-typed-pointer> */ pointer,
  456.                  obj_t /* <integer> */ offset)
  457. {
  458.     void *ptr = C_PTR(pointer)->pointer;
  459.     int true_offset = fixnum_value(offset);
  460.     
  461.     if (!obj_is_fixnum(offset))
  462.     error("Offset is not fixnum: %=", offset);
  463.     *((short *)((int)ptr + true_offset)) = fixnum_value(value);
  464.     return value;
  465. }
  466.  
  467. obj_t unsigned_short_at(obj_t /* <statically-typed-pointer> */ pointer,
  468.             obj_t /* <integer> */ offset)
  469. {
  470.     void *ptr = C_PTR(pointer)->pointer;
  471.     int true_offset = fixnum_value(offset);
  472.     
  473.     if (!obj_is_fixnum(offset))
  474.     error("Offset is not fixnum: %=", offset);
  475.     return make_fixnum(*((unsigned short *)((int)ptr + true_offset)));
  476. }
  477.  
  478. obj_t unsigned_short_at_setter(obj_t /* <integer> */ value,
  479.                    obj_t /* <statically-typed-pointer> */ pointer,
  480.                    obj_t /* <integer> */ offset)
  481. {
  482.     void *ptr = C_PTR(pointer)->pointer;
  483.     int true_offset = fixnum_value(offset);
  484.     
  485.     if (!obj_is_fixnum(offset))
  486.     error("Offset is not fixnum: %=", offset);
  487.     *((unsigned short *)((int)ptr + true_offset)) = fixnum_value(value);
  488.     return value;
  489. }
  490.  
  491. obj_t signed_long_at(obj_t /* <statically-typed-pointer> */ pointer,
  492.              obj_t /* <integer> */ offset)
  493. {
  494.     void *ptr = C_PTR(pointer)->pointer;
  495.     int true_offset = fixnum_value(offset);
  496.     
  497.     if (!obj_is_fixnum(offset))
  498.     error("Offset is not fixnum: %=", offset);
  499.     return make_fixnum(*((long *)((int)ptr + true_offset)));
  500. }
  501.  
  502. obj_t signed_long_at_setter(obj_t /* <integer> */ value,
  503.                 obj_t /* <statically-typed-pointer> */ pointer,
  504.                 obj_t /* <integer> */ offset)
  505. {
  506.     void *ptr = C_PTR(pointer)->pointer;
  507.     int true_offset = fixnum_value(offset);
  508.     
  509.     if (!obj_is_fixnum(offset))
  510.     error("Offset is not fixnum: %=", offset);
  511.     *((long *)((int)ptr + true_offset)) = fixnum_value(value);
  512.     return value;
  513. }
  514.  
  515. obj_t unsigned_long_at(obj_t /* <statically-typed-pointer> */ pointer,
  516.                obj_t /* <integer> */ offset)
  517. {
  518.     void *ptr = C_PTR(pointer)->pointer;
  519.     int true_offset = fixnum_value(offset);
  520.     
  521.     if (!obj_is_fixnum(offset))
  522.     error("Offset is not fixnum: %=", offset);
  523.     return make_fixnum(*((unsigned long *)((int)ptr + true_offset)));
  524. }
  525.  
  526. obj_t unsigned_long_at_setter(obj_t /* <integer> */ value,
  527.                   obj_t /* <statically-typed-pointer> */ pointer,
  528.                   obj_t /* <integer> */ offset)
  529. {
  530.     void *ptr = C_PTR(pointer)->pointer;
  531.     int true_offset = fixnum_value(offset);
  532.     
  533.     if (!obj_is_fixnum(offset))
  534.     error("Offset is not fixnum: %=", offset);
  535.     *((unsigned long *)((int)ptr + true_offset)) = fixnum_value(value);
  536.     return value;
  537. }
  538.  
  539. obj_t pointer_at(obj_t /* <statically-typed-pointer> */ pointer,
  540.          obj_t /* <integer> */ offset,
  541.          obj_t /* <class> */ cls)
  542. {
  543.     void *ptr = C_PTR(pointer)->pointer;
  544.     int true_offset = fixnum_value(offset);
  545.     
  546.     if (!obj_is_fixnum(offset))
  547.     error("Offset is not fixnum: %=", offset);
  548.     if (!instancep(cls, obj_StaticTypeClass))
  549.     error("class is not statically typed pointer: %=", cls);
  550.     /* pointer size object -- dereference as (void **) */
  551.     return convert_c_object(cls, *(void **)((char *)ptr + true_offset),
  552.                 FALSE);
  553. }
  554.  
  555. obj_t pointer_at_setter(obj_t /* <statically-typed-pointer> */ value,
  556.             obj_t /* <statically-typed-pointer> */ pointer,
  557.             obj_t /* <integer> */ offset)
  558. {
  559.     void *ptr = C_PTR(pointer)->pointer;
  560.     int true_offset = fixnum_value(offset);
  561.     
  562.     if (!obj_is_fixnum(offset))
  563.     error("Offset is not fixnum: %=", offset);
  564.     /* pointer size object -- dereference as (void **) */
  565.     *((void **)((char *)ptr + true_offset)) = get_c_object(value);
  566.     return value;
  567. }
  568.  
  569. obj_t pointer_add(obj_t /* <statically-typed-pointer> */ pointer,
  570.           obj_t /* <integer> */ num)
  571. {
  572.     void *ptr = C_PTR(pointer)->pointer;
  573.     int true_offset = fixnum_value(num);
  574.     
  575.     return make_c_pointer(object_class(pointer),
  576.               (void *)((int)ptr + true_offset));
  577. }
  578.     
  579. obj_t pointer_subtract(obj_t /* <statically-typed-pointer> */ pointer1,
  580.                obj_t /* <statically-typed-pointer> */ pointer2)
  581. {
  582.     void *ptr1 = C_PTR(pointer1)->pointer;
  583.     void *ptr2 = C_PTR(pointer2)->pointer;
  584.     
  585.     return make_fixnum((long int)ptr1 - (long int)ptr2);
  586. }
  587.     
  588.  
  589. /* Dereferences a "slot" in the "structure" pointed to by a <c-pointer>. */
  590. obj_t c_pointer_field(obj_t pointer, obj_t offset, obj_t cls, obj_t deref)
  591. {
  592.     void *ptr = C_PTR(pointer)->pointer;
  593.     int true_offset = fixnum_value(offset);
  594.  
  595.     if (deref == obj_False)
  596.     /* Don't dereference -- just increment */
  597.     return convert_c_object(cls, (void *)((int)ptr + true_offset), FALSE);
  598.     else if (cls == obj_CharacterClass || cls == obj_BooleanClass)
  599.     /* byte size object -- dereference as (char *) */
  600.     return convert_c_object(cls, (void *)*((char *)ptr + true_offset),
  601.                 FALSE);
  602.     else
  603.     /* pointer size ofject -- dereference as (void **) */
  604.     return convert_c_object(cls, *(void **)((char *)ptr + true_offset),
  605.                 FALSE);
  606. }
  607.  
  608. /* Sets the value of a "slot" in the "structure" pointed to by a */
  609. /* <c-pointer>. */
  610. obj_t c_pointer_field_setter(obj_t value, obj_t /* <c-pointer> */ pointer,
  611.                  obj_t /* <integer> */ offset)
  612. {
  613.     obj_t cls = object_class(value);
  614.     void *ptr = C_PTR(pointer)->pointer;
  615.     int true_offset = fixnum_value(offset);
  616.  
  617.     if (cls == obj_CharacterClass || cls == obj_BooleanClass)
  618.     /* byte size object -- dereference as (char *) */
  619.     *((char *)ptr + true_offset) = ((char) get_c_object(value));
  620.     else
  621.     /* pointer size ofject -- dereference as (void **) */
  622.     *((void **)((char *)ptr + true_offset)) = get_c_object(value);
  623.     return value;
  624. }
  625.  
  626. obj_t c_pointer_as(obj_t /* <class> */ cls,
  627.            obj_t /* <statically-typed-pointer> */ object)
  628. {
  629.     if (instancep(object, cls))
  630.     return object;
  631.     else
  632.     return make_c_pointer(cls, C_PTR(object)->pointer);
  633. }
  634.  
  635. obj_t c_ptr_as_int(obj_t /* <class> */ cls,
  636.            obj_t /* <statically-typed-pointer> */ object)
  637. {
  638.     return make_fixnum((int) C_PTR(object)->pointer);
  639. }
  640.  
  641. obj_t c_int_as_ptr(obj_t /* <class> */ cls,
  642.            obj_t /* <integer> */ object)
  643. {
  644.     if (instancep(object, cls))
  645.     return object;
  646.     else
  647.     return make_c_pointer(cls, (void *)fixnum_value(object));
  648. }
  649.  
  650. obj_t c_pointer_equal(obj_t left, obj_t right)
  651. {
  652.     if (C_PTR(left)->pointer == C_PTR(right)->pointer)
  653.     return obj_True;
  654.     else
  655.     return obj_False;
  656. }
  657.  
  658. /* GC routines. */
  659.  
  660. int scav_c_pointer(struct object *obj)
  661. {
  662.     return sizeof(struct c_pointer);
  663. }
  664.  
  665. obj_t trans_c_pointer(obj_t cptr)
  666. {
  667.     return transport(cptr, sizeof(struct c_pointer));
  668. }
  669.  
  670. static int scav_foreign_file(struct object *obj)
  671. {
  672.     scavenge(&((struct foreign_file *)obj)->file_name);
  673.     return sizeof(struct foreign_file)
  674.     + ((struct foreign_file *)obj)->extra_size;
  675. }
  676.  
  677. static obj_t trans_foreign_file(obj_t cptr)
  678. {
  679.     return transport(cptr, sizeof(struct foreign_file)
  680.                     + FOREIGN_FILE(cptr)->extra_size);
  681. }
  682.  
  683. void scavenge_c_roots(void)
  684. {
  685.     scavenge(&obj_CPointerClass);
  686.     scavenge(&obj_ForeignFileClass);
  687.     scavenge(&obj_NullPointer);
  688.     if (mindy_dynamic_syms != NULL)
  689.     /* Let it be scavenged and we'll recreate it at need */
  690.     mindy_dynamic_syms = NULL;
  691.     scavenge(&mindy_explicit_syms);
  692. }
  693.  
  694.  
  695. /* Init stuff. */
  696.  
  697. void make_c_classes(void)
  698. {
  699.     obj_CPointerClass
  700.     = make_builtin_class(scav_c_pointer, trans_c_pointer);
  701.     CLASS(obj_CPointerClass)->class = obj_StaticTypeClass;
  702.     CLASS(obj_CPointerClass)->sealed_p = FALSE;
  703.     obj_ForeignFileClass
  704.     = make_builtin_class(scav_foreign_file, trans_foreign_file);
  705. }
  706.  
  707. void init_c_classes(void)
  708. {
  709.     init_builtin_class(obj_CPointerClass, "<statically-typed-pointer>",
  710.                obj_ObjectClass, NULL);
  711.     def_printer(obj_CPointerClass, print_c_pointer);
  712.     init_builtin_class(obj_ForeignFileClass, "<foreign-file>", obj_ObjectClass,
  713.                NULL);
  714.     def_printer(obj_ForeignFileClass, print_foreign_file);
  715. }
  716.  
  717. void init_c_functions(void)
  718. {
  719.     extern void build_explicit_syms(void);
  720.     
  721.     /* This is required by find_c_function and find_c_pointer */
  722.     build_explicit_syms();
  723.     
  724.     define_method("find-c-function",
  725.           list1(obj_ByteStringClass), FALSE,
  726.           list1(pair(symbol("file"), obj_Unbound)),
  727.           FALSE, obj_ObjectClass, find_c_function);
  728.     define_method("find-c-pointer",
  729.           list1(obj_ByteStringClass), FALSE,
  730.           list1(pair(symbol("file"), obj_Unbound)),
  731.           FALSE, obj_ObjectClass, find_c_ptr);
  732.     define_method("load-object-file",
  733.           list1(obj_ListClass), FALSE,
  734.           list1(pair(symbol("include"), obj_Nil)), FALSE,
  735.           obj_ObjectClass, load_c_file);
  736.     define_method("signed-byte-at", list1(obj_CPointerClass), FALSE,
  737.           list1(pair(symbol("offset"), make_fixnum(0))), FALSE,
  738.           obj_IntegerClass, signed_byte_at);
  739.     define_method("signed-byte-at-setter",
  740.           list2(obj_IntegerClass, obj_CPointerClass), FALSE,
  741.           list1(pair(symbol("offset"), make_fixnum(0))), FALSE,
  742.           obj_IntegerClass, signed_byte_at_setter);
  743.     define_method("unsigned-byte-at", list1(obj_CPointerClass), FALSE,
  744.           list1(pair(symbol("offset"), make_fixnum(0))), FALSE,
  745.           obj_IntegerClass, unsigned_byte_at);
  746.     define_method("unsigned-byte-at-setter",
  747.           list2(obj_IntegerClass, obj_CPointerClass), FALSE,
  748.           list1(pair(symbol("offset"), make_fixnum(0))), FALSE,
  749.           obj_IntegerClass, unsigned_byte_at_setter);
  750.     define_method("signed-short-at", list1(obj_CPointerClass), FALSE,
  751.           list1(pair(symbol("offset"), make_fixnum(0))), FALSE,
  752.           obj_IntegerClass, signed_short_at);
  753.     define_method("signed-short-at-setter",
  754.           list2(obj_IntegerClass, obj_CPointerClass), FALSE,
  755.           list1(pair(symbol("offset"), make_fixnum(0))), FALSE,
  756.           obj_IntegerClass, signed_short_at_setter);
  757.     define_method("unsigned-short-at", list1(obj_CPointerClass), FALSE,
  758.           list1(pair(symbol("offset"), make_fixnum(0))), FALSE,
  759.           obj_IntegerClass, unsigned_short_at);
  760.     define_method("unsigned-short-at-setter",
  761.           list2(obj_IntegerClass, obj_CPointerClass), FALSE,
  762.           list1(pair(symbol("offset"), make_fixnum(0))), FALSE,
  763.           obj_IntegerClass, unsigned_short_at_setter);
  764.     define_method("signed-long-at", list1(obj_CPointerClass), FALSE,
  765.           list1(pair(symbol("offset"), make_fixnum(0))), FALSE,
  766.           obj_IntegerClass, signed_long_at);
  767.     define_method("signed-long-at-setter",
  768.           list2(obj_IntegerClass, obj_CPointerClass), FALSE,
  769.           list1(pair(symbol("offset"), make_fixnum(0))), FALSE,
  770.           obj_IntegerClass, signed_long_at_setter);
  771.     define_method("unsigned-long-at", list1(obj_CPointerClass), FALSE,
  772.           list1(pair(symbol("offset"), make_fixnum(0))), FALSE,
  773.           obj_IntegerClass, unsigned_long_at);
  774.     define_method("unsigned-long-at-setter",
  775.           list2(obj_IntegerClass, obj_CPointerClass), FALSE,
  776.           list1(pair(symbol("offset"), make_fixnum(0))), FALSE,
  777.           obj_IntegerClass, unsigned_long_at_setter);
  778.     define_method("pointer-at", list1(obj_CPointerClass), FALSE,
  779.           list2(pair(symbol("offset"), make_fixnum(0)),
  780.             pair(symbol("class"), obj_CPointerClass)), FALSE,
  781.           obj_IntegerClass, pointer_at);
  782.     define_method("pointer-at-setter",
  783.           list2(obj_CPointerClass, obj_CPointerClass), FALSE,
  784.           list1(pair(symbol("offset"), make_fixnum(0))), FALSE,
  785.           obj_IntegerClass, pointer_at_setter);
  786.     define_method("+", list2(obj_CPointerClass, obj_IntegerClass), FALSE,
  787.           obj_False, FALSE, obj_CPointerClass, pointer_add);
  788.     define_method("-", list2(obj_CPointerClass, obj_CPointerClass), FALSE,
  789.           obj_False, FALSE, obj_IntegerClass, pointer_subtract);
  790.     define_method("c-pointer-slot",
  791.           listn(4, obj_CPointerClass, obj_IntegerClass,
  792.             obj_TypeClass, obj_ObjectClass),
  793.           FALSE, obj_False, FALSE,
  794.           obj_ObjectClass, c_pointer_field);
  795.     define_method("c-pointer-slot-setter",
  796.           list3(obj_ObjectClass, obj_CPointerClass, obj_IntegerClass),
  797.           FALSE, obj_False, FALSE,
  798.           obj_ObjectClass, c_pointer_field_setter);
  799.     define_method("as",
  800.           list2(obj_StaticTypeClass, obj_CPointerClass), FALSE,
  801.           obj_False, FALSE,
  802.           obj_ObjectClass, c_pointer_as);
  803.     define_method("as",
  804.           list2(obj_IntegerClass, obj_CPointerClass), FALSE,
  805.           obj_False, FALSE,
  806.           obj_ObjectClass, c_ptr_as_int);
  807.     define_method("as",
  808.           list2(obj_StaticTypeClass, obj_IntegerClass), FALSE,
  809.           obj_False, FALSE,
  810.           obj_ObjectClass, c_int_as_ptr);
  811.     define_method("=", list2(obj_CPointerClass, obj_CPointerClass),
  812.           FALSE, obj_False, FALSE,
  813.           obj_BooleanClass, c_pointer_equal);
  814.     obj_NullPointer = make_c_pointer(obj_CPointerClass, 0);
  815.     define_constant("null-pointer", obj_NullPointer);
  816. }
  817.